home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 1
/
Cream of the Crop 1.iso
/
PROGRAM
/
CGAMEJOY.ARJ
/
JOYSTKLO.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-01-08
|
12KB
|
270 lines
/* joystklo.c Low level game-adapter port access functions.
The functions in this module
1. detect the presence of a game adapter
2. verify which axes are functional
3. read current button status
4. read changed button status
5. read current joystick resistance position
6. allow change of active axes within this system
as long as they have been found functional.
See file joystklo.se for pseudo code/structured english
and joystick.doc for an explanation of the functions.
This module was written for Borland C++ 2.0.
No C++ extensions were used, this is all C and Assembler.
I've done limited testing on an old XT with 11/08/82 BIOS
and on my PS/2 like 386 AT and haven't found anything yet...
If you find this module useful, great!!!
This module has been released to the public domain
Tue 01-07-1992 23:30:18
by Ed Torgerson : CIS 70313,456, GEnie E.TORGERSON1.
any constructive correspondence is welcome.
Thanks to Gary Blaine, for putting out JOY.ARC for all to use.
-----------------------------------------------------------------------------*/
#include <dos.h>
#pragma inline
/*-- Global defines -----*/
#define NOP 0x90 /* define NOP instruction for __emit__ delay */
#define TIME_OUT 1000 /* one-shot time out value for reading position */
/* N.B. Interrupts are disabled during timing */
/* N.B. My loops are faster than Gary Blaine's, */
/* the TIME_OUT value is proportionally higher. */
/*-- Global variables -----*/
unsigned char G_Stick_Active_Axes ; /* bit mask of currently active axes */
unsigned char G_Stick_Valid_Axes ; /* bit mask of valid axes */
unsigned char G_LastCallState = 0xF0 ; /* bit image of last button state */
/*-- Function Prototypes -----*/
int JstGetChangedButton( void ) ; /* get changed button status */
int JstGetButton( void ) ; /* get present button status */
int JstGetPosition(int axis_mask) ; /* get position on given axis */
int JstDetect ( void ) ; /* detect active game port lines */
int JstGetValidAxes ( void ) ; /* return mask of valid axes */
int JstGetActiveAxes( void ) ; /* return mask of active axes */
int JstSetActiveAxes( unsigned mask) ; /* set mask of active axes */
/*-- Function Definitions ---------------------------------------------------*/
int JstGetValidAxes ( void ) /* return bit mask of valid axes */
{
return ( (unsigned) G_Stick_Valid_Axes ) ;
}
/*---------------------------------------------------------------------------*/
int JstGetActiveAxes( void ) /* return bit mask of active axes */
{
return ( (unsigned) G_Stick_Active_Axes ) ;
}
/*---------------------------------------------------------------------------*/
int JstSetActiveAxes( unsigned mask ) /* set bit mask of active axes */
{
asm {
mov ax, mask ; /* get axis mask to set */
and al, G_Stick_Valid_Axes ; /* set check value */
cmp al, mask ; /* compare mask to check value */
je ValidUserAxis ; /* valid if equal */
}
return ( 0 ) ; /* invalid mask */
ValidUserAxis:
G_Stick_Active_Axes = (unsigned char) mask ;
return ( 1 ) ; /* success */
}
/*---------------------------------------------------------------------------*/
int JstDetect ( ) /* detect active game port lines */
{
register unsigned char x, y ;
outportb ( 0x201, 0 ) ; /* initialize game adapter one-shot timers */
delay (200) ; /* give the timers a chance to clear */
x = inportb ( 0x201 ) ; /* get initial game adapter position flags */
x = x & 0xf ; /* lose upper nibble */
outportb ( 0x201, 0 ) ; /* initialize game adapter one-shot timers */
__emit__(NOP);
__emit__(NOP);
__emit__(NOP);
__emit__(NOP);
__emit__(NOP);
y = inportb ( 0x201 ) ; /* get initial game adapter position flags */
y = y & 0xf ; /* lose upper nibble */
x = x ^ y ; /* any axes that change are functional */
G_Stick_Active_Axes = x ; /* set currently active axes */
G_Stick_Valid_Axes = x ; /* set valid axes mask */
return ( (unsigned) x ) ;
} /*-- end JstDetect */
/*---------------------------------------------------------------------------*/
int JstGetButton() /* get present button status */
{
asm {
mov dx, 201h ; /* port address of game adapter */
in al, dx ; /* al = game port state */
and al, 0xF0 ; /* lose lower nibble */
mov G_LastCallState, al ; /* save button state for next call */
xor al, 0xF0 ; /* flip bits */
mov dh, al ; /* dl = button down mask */
xor al, 0xF0 ; /* al = button up mask */
mov cl, 4
shr al, cl ; /* shift mask to lower nibble */
or al, dh ; /* al = combined button event mask */
xor ah, ah ; /* zero out ah for return */
}
return (_AX) ;
} /*-- end JstGetButton */
/*---------------------------------------------------------------------------*/
int JstGetChangedButton( ) /* get changed button status */
{
asm {
mov dx, 201h ; /* port address of game adapter */
in al, dx ; /* al = game port state */
and al, 0xF0 ; /* lose lower nibble */
mov dh, al ; /* dl = current button state */
xor al, G_LastCallState ; /* al = changed button mask */
jnz ButtonChanged
}
return (0) ;
ButtonChanged:
asm {
mov dl, G_LastCallState ; /* dl = last call state */
mov G_LastCallState, dh ; /* save button state for next call */
and dl, al ; /* dl = button down mask */
xor al, dl ; /* al = button up mask */
mov cl, 4
shr al, cl ; /* shift mask to lower nibble */
or al, dl ; /* al = combined button event mask */
xor ah, ah ; /* zero out ah for return */
}
return (_AX) ;
} /*-- end JstGetChangedButton */
/*---------------------------------------------------------------------------*/
int JstGetPosition(int axis_mask ) /* get position on given axis */
{
asm {
mov al, G_Stick_Active_Axes ; /* get currently active axes */
test al, axis_mask ; /* check if given axis is active */
jnz ValidAxis ; /* go on if valid */
}
return (0) ; /* error - invalid parameter given */
ValidAxis:
asm {
cli ; /* disable interrupts for accurate timing */
mov dx, 0x43 ; /* 8253 write command port */
xor al, al ; /* 8253 latch timer 0 command */
out dx,al
nop ; /* delay so latch regs can be filled */
nop
nop
nop
nop
mov dx, 0x40 ; /* 8253 read port */
in al, dx ; /* read low byte of 8253 timer count */
mov cl, al ; /* copy to CL */
nop ; /* delay so latch regs can be filled */
nop
nop
mov dx, 0x40 ; /* 8253 read port */
in al, dx ; /* read high byte of 8253 timer count */
mov ch, al ; /* !!!! CX = start_time !!!!*/
push cx ; /* just to be safe */
;----- /* Time to start timin' */
mov dx, 0x201 ; /* write to game adapter */
mov al, 0 ; /* initialize one-shot timers */
out dx, al ;
xor si, si ; /* set up timing loop */
mov bx, axis_mask ; /* get axis mask for quick read */
}
DoLoop1:
asm {
mov dx, 0x201 ; /* read game adapter */
in al, dx ;
test al, bl ; /* test for matching bit */
jz short DoneLoop1 ; /* go on if match */
inc si ;
cmp si, TIME_OUT ; /* quit if timed out */
jz short Quit0 ;
jmp short DoLoop1 ; /* loop back */
}
Quit0:
asm {
sti ; /* re-enable interrupts */
}
return (0) ; ; /* error - loop timed out */
DoneLoop1:
asm {
mov dx, 0x43 ; /* 8253 write command port */
xor al, al ; /* 8253 latch timer 0 command */
out dx,al
nop ; /* delay so latch regs can be filled */
nop
nop
nop
nop
mov dx, 0x40 ; /* 8253 read port */
in al, dx ; /* read low byte of 8253 timer count */
mov bl, al ; /* copy to BL */
nop ; /* delay so latch regs can be filled */
nop
nop
mov dx, 0x40 ; /* 8253 read port */
in al, dx ; /* read high byte of 8253 timer count */
mov bh, al ; /* !!!! BX = finish_time !!!! */
sti ; /* re-enable interrupts */
}
asm {
pop cx ; /* start time */
cmp cx, bx ; /* jump if start < finish */
jb short StartIsLess
sub cx, bx ; /* result = start - finish; */
mov ax, cx ; /* !!!! AX = result !!!! */
jmp short AdjustResult
}
StartIsLess:
asm {
mov ax, 65535 ; /* result = 0xffff - finish + start */
sub ax, bx
add ax, cx ; /* !!!! AX = result !!!! */
}
AdjustResult:
asm {
and ax, 8176 ; /* result & 0x1ff0 */
mov cl, 4 ;
shr ax, cl ; /* result = result >> 4 */
push ax ; /* save ax */
xor si, si ; /* set up loop to clear rest of bits */
mov cl, G_Stick_Valid_Axes ; /* get mask of valid axes */
not cl ; /* flip axis mask for test */
and cl, 0xf ; /* just to be sure... */
}
DoLoop2:
asm {
mov dx, 0x201 ; /* read game adapter */
in al, dx ;
and al, 0xf ; /* lose upper nibble */
cmp al, cl ; /* check if all bits have flipped */
jz DoneLoop2 ; /* jump if we're done */
inc si ; /* increment counter */
cmp si, TIME_OUT ; /* quit if timed out */
jz short DoneLoop2
jmp short DoLoop2 ; /* loop back */
}
DoneLoop2:
asm {
pop ax ; /* get back our result */
}
return (_AX) ;
} /* end JstGetPosition */
/*---------------------------------------------------------------------------*/
/* end joystklo.c */